package com.app.security.satoken.config;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.app.core.configuration.CommonProperties;
import com.app.core.mvc.result.Code;
import com.app.core.redis.CommonRedisKey;
import com.app.core.security.Principal;
import com.app.core.security.ResourceOwnerContext;
import com.app.core.security.TokenStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @author qiangt
 * @version 1.0
 * @date 2023/10/17 14:39
 * @description: Redis实现当前用户操作
 */
@RequiredArgsConstructor
@Slf4j
@Component
public class RedisResourceOwnerContext implements ResourceOwnerContext {

    private final StringRedisTemplate stringRedisTemplate;

    private final CommonProperties commonProperties;

    @Override
    public Principal getPrincipal() {
        String token = null;
        try {
            token = StpUtil.getTokenValue();
        } catch (Exception e) {
            log.warn(Code.A00031.message(), e);
            return Principal.defaultPrincipal();
        }
        return getRedisPrincipal(token);
    }

    @Override
    public Principal getPrincipal(HttpServletRequest request) {
        String token = request.getHeader(commonProperties.getTokenHeader());
        return getRedisPrincipal(token);
    }

    @Override
    public Principal getPrincipal(String token) {
        return getRedisPrincipal(token);
    }

    @Override
    public void setPrincipal(Principal principal) {
        Assert.notNull(principal);
        StpUtil.login(principal.getIdentity());
        stringRedisTemplate.opsForValue().set(CommonRedisKey.UserInfo.key(Convert.toStr(principal.getIdentity())), JSON.toJSONString(principal), CommonRedisKey.UserInfo.timeout(), CommonRedisKey.UserInfo.unit());
    }

    private Principal getRedisPrincipal(String token) {
        String userInfoJson = stringRedisTemplate.opsForValue().get(CommonRedisKey.UserInfo.key(TokenStrategy.tokenToUserId(token)));
        if (StrUtil.isNotBlank(userInfoJson)) {
            return JSONObject.parseObject(userInfoJson, Principal.class);
        }
        return Principal.defaultPrincipal();
    }
}
